<?php
	require_once(dirname(__FILE__).'/easy_runner.php');
	require_once(dirname(__FILE__).'/../router.php');
	
	class WhenRoutePatternIsExtractingParameters extends UnitTestCase {
	
		public function testRoutePatternCanExtractParameter() {
			$pattern = new RoutePattern('articles/:year');
			$parameters = $pattern->extractParameters('articles/2006');
			$this->assertEqual($parameters['year'], 2006);
		}
		
		public function testRoutePatternReturnsFalseWhenPatternDoesNotMatchPath() {
			$pattern = new RoutePattern('articles/:year');
			$parameters = $pattern->extractParameters('blabla/2006');
			$this->assertFalse($parameters);
		}

		public function testRoutePatternCanExtractDifferentPlaceholderName() {
			$pattern = new RoutePattern('articles/:id');
			$parameters = $pattern->extractParameters('articles/4');
			$this->assertEqual($parameters['id'], 4);
		}

		public function testRoutePatternCanExtractOnDifferentLevel() {
			$pattern = new RoutePattern('articles/category/:category');
			$parameters = $pattern->extractParameters('articles/category/php');
			$this->assertEqual($parameters['category'], 'php');
		}
		
		public function testRoutePatternReturnsFalseOnLongerPath() {
			$pattern = new RoutePattern('articles/:name');
			$parameters = $pattern->extractParameters('articles/category/php');
			$this->assertFalse($parameters);
		}

		public function testRoutePatternCanApplyDefaultValue() {
			$pattern = new RoutePattern('articles/:action');
			$pattern->setDefaultFor('action', 'browse');
			$parameters = $pattern->extractParameters('articles');
			$this->assertEqual($parameters['action'], 'browse');
		}
		
		public function testRoutePatternCanOverloadDefaultValue() {
			$pattern = new RoutePattern('articles/:action');
			$pattern->setDefaultFor('action', 'browse');
			$parameters = $pattern->extractParameters('articles/add');
			$this->assertEqual($parameters['action'], 'add');
		}
		
		public function testRoutePatternReturnsFalseOnShortPath() {
			$pattern = new RoutePattern('articles/:action');
			$parameters = $pattern->extractParameters('articles');
			$this->assertFalse($parameters);
		}
		
		public function testRoutePatternReturnsDefaultThatIsNotInPattern() {
			$pattern = new RoutePattern('articles/:category');
			$pattern->setDefaultFor('controller', 'ArticleController');
			$parameters = $pattern->extractParameters('articles/php');
			$this->assertEqual($parameters['category'], 'php');
			$this->assertEqual($parameters['controller'], 'ArticleController');
		}
		
		public function testRoutePatternCanExtractMultipleValues() {
			$pattern = new RoutePattern('articles/:id/:action');
			$parameters = $pattern->extractParameters('articles/4/comments');
			$this->assertEqual($parameters['id'], 4);
			$this->assertEqual($parameters['action'], 'comments');
		}
		
		public function testRoutePatternRetursFalseOnMissingPlaceholderValue() {
			$pattern = new RoutePattern('articles/:id/:action');
			$parameters = $pattern->extractParameters('articles/4');
			$this->assertFalse($parameters);
		}
		
		public function testRoutePatternReturnsFalseOnUnsatisfiedRule() {
			$pattern = new RoutePattern('articles/:id');
			$pattern->setRegexRuleFor('id', '/^[0-9]$/');
			$parameters = $pattern->extractParameters('articles/blabla');
			$this->assertFalse($parameters);
		}
		
		public function testRouteExactMatch() {
			$pattern = new RoutePattern('articles/add');
			$parameters = $pattern->extractParameters('articles/add');
			$this->assertEqual($parameters, array());
		}
		
		public function testRoutePatternPriorityPrecedence() {
			$high = new RoutePattern('articles/add');
			$low = new RoutePattern('articles/:sid');
			$this->assertTrue($high->hasHigherPriorityThan($low));
			$this->assertFalse($low->hasHigherPriorityThan($high));
		}
		
		public function testRouterPatternSpecialPriorityPrecedence() {
			$high = new RoutePattern('articles/:sid');
			$low = new RoutePattern(':category/add');
			$this->assertTrue($high->hasHigherPriorityThan($low));
			$this->assertFalse($low->hasHigherPriorityThan($high));
		}
		
		public function testRouterPatternCanMatchEmptyString() {
			$pattern = new RoutePattern('');
			$pattern->setDefaultFor('action', 'index');
			$parameters = $pattern->extractParameters('');
			$this->assertIdentical($parameters, array('action' => 'index'));
		}
		
		public function testRoutePatternCanHandleAdditionalSlashesInPath() {
			$pattern = new RoutePattern('articles/add');
			$parameters = $pattern->extractParameters('/articles/add/');
			$this->assertIdentical($parameters, array());
		}
		
		public function testRoutePatternCanHandleAdditionalSlashesInPattern() {
			$pattern = new RoutePattern('/articles/add/');
			$parameters = $pattern->extractParameters('articles/add');
			$this->assertIdentical($parameters, array());
		}
		
		public function testRoutePatternMatchesValueWithSuffix(){
			$pattern = new RoutePattern('/article/:title.html');
			$parameters = $pattern->extractParameters('/article/hello.html');
			$this->assertEqual($parameters['title'], 'hello');
		}
      
		public function testRoutePatternWithSuffixReturnsFalseOnNoMatch(){
			$pattern = new RoutePattern('article/:title.html');
			$parameters = $pattern->extractParameters('article/hello');
			$this->assertFalse($parameters);
		}
		
	}
	
	class WhenRoutePatternIsCreatingPath extends UnitTestCase {
		
		public function testPatternCreatesPathWithMultipleDefaultParameters() {
			$pattern = new RoutePattern('articles/:category/:sid');
			$pattern->setDefaultFor('category', 'all');
			$pattern->setDefaultFor('sid', 'default');
			$parameters = array();
			$path = $pattern->createPath($parameters);
			$this->assertEqual($path, 'articles');
		} 
		
		public function testPatternCreatesPathWithSpreadMultipleDefaultParameters() {
			$pattern = new RoutePattern('articles/:category/something/:sid');
			$pattern->setDefaultFor('category', 'all');
			$pattern->setDefaultFor('sid', 'default');
			$parameters = array();
			$path = $pattern->createPath($parameters);
			$this->assertEqual($path, 'articles/all/something');
		} 
		
		public function testPatternCreatesPathWithOverriddenDefaultParameter() {
			$pattern = new RoutePattern('articles/:category');
			$parameters = array('category' => 'php');
			$path = $pattern->createPath($parameters);
			$this->assertEqual($path, 'articles/php');
		} 
		
		public function testPatternCanCreateBlankPath() {
			$pattern = new RoutePattern(':page');
			$pattern->setDefaultFor('page', 'index');
			$parameters = array();
			$path = $pattern->createPath($parameters);
			$this->assertEqual($path, '');
		}
		
		public function testPatternCannotCreatePathOnUnsatisfiedRule() {
			$pattern = new RoutePattern('articles/:id');
			$pattern->setRegexRuleFor('id', '/^[0-9]$/');
			$parameters = array('id' => 'index');
			$path = $pattern->createPath($parameters);
			$this->assertFalse($path);
		}

		public function testPatternCanExtractPlaceholderName() {
			$placeHolderName = RoutePattern::getPlaceholderName(":sid");
			$this->assertEqual("sid",$placeHolderName);
		}

		public function testPatternCannotExtractNonPlaceholderName() {
			$placeHolderName = RoutePattern::getPlaceholderName("a-car");
			$this->assertFalse($placeHolderName);
		}
		
		public function testRoutePatternReturnsFalseOnUmnatchingDefaultValueWhichDoesNotAppearInPattern() {
			$first = new RoutePattern('articles/:sid');
			$first->setDefaultFor('controller','articles');
			$path = $first->createPath(array('controller'=>'pages','sid'=>'about'));
			$this->assertFalse($path);
		}
		
		public function testRoutePatternReturnsPathOnUmnatchingDefaultValueWhichDoesAppearInPattern() {
			$first = new RoutePattern('articles/:category/:sid');
			$first->setDefaultFor('category','howtos');
			$path = $first->createPath(array('category'=>'geeky-stuff','sid'=>'about'));
			$this->assertEqual($path, 'articles/geeky-stuff/about');
		}

		public function testRoutePatternReturnsPathOnWhenHiddenDefaultValueDoesNotAppearInParameters() {
			$first = new RoutePattern('clanky/:sid');
			$first->setDefaultFor('controller','aticle');
			$path = $first->createPath(array('sid'=>'about'));
			$this->assertEqual($path, 'clanky/about');
		}
		
	}
	
	if(EasyRunner::isRunner()) {
		$test = new GroupTest('RoutePatternTests');
		$test->addTestCase(new WhenRoutePatternIsExtractingParameters());
		$test->addTestCase(new WhenRoutePatternIsCreatingPath());		
		EasyRunner::run($test);
	}
?>